package com.xpec.c4.codec.h2o;

import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Debug {
	/**
	 * 打印对象内容
	 * 
	 * @param <T>
	 * 
	 * @param object
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public static void printObject(Object object) throws Exception {
		if (object == null) {
			System.out.println("null");
			return;
		}

		Class type = object.getClass();

		if (type.isArray()) {
			int length = Array.getLength(object);
			for (int i = 0; i < length; i++) {
				Object value = Array.get(object, i);
				System.out.println("=======object " + i);
				printObject(value);
			}
		} else if (type.isEnum()) {
			System.out.println(type.getName() + " (enum)= " + object);
		} else if (object instanceof Collection) {// 集合
			Iterable iter = (Iterable) object;
			for (Object obj : iter) {
				System.out.println("=====Iterable object");
				printObject(obj);
			}
		} else if (object instanceof Map) {// map
			Map map = (Map) object;
			
			Set set = map.keySet();
			
			int size = set.size();
			
			System.out.println("=======print map,size:" + size);
			
			int idx = 0;
			Iterator iter = set.iterator();
			while(iter.hasNext()){
				
				Object key = iter.next();
				
				System.out.println("key = {");
				printObject(key);
				System.out.println("}");
				
				System.out.println("value = {");
				printObject(map.get(key));
				System.out.println("}");
			}			
		} else if (CodedInfo.classIngeterMapping.containsKey(type)) {
			Field[] fields = object.getClass().getDeclaredFields();

			// do short
			CodedInfo.sort(fields);
						
			System.out.println("===printObject====>");
			for (Field f : fields) {
				f.setAccessible(true);
				
				if(Modifier.isFinal(f.getModifiers())){
					System.out.print("<final> ");
				}
				if(Modifier.isStatic(f.getModifiers())){
					System.out.print("<static> ");
				}
				
				System.out.println(f.getName() + " = {");
				printObject(f.get(object));
				System.out.println("}");
			}
		} else {
			System.out.println(object);
		}

	}
	
	/**
	 * 以二进制方式打印
	 * 
	 * @param r
	 */
	public static void printBinary(byte[] r) {
		if (r != null) {
			System.out.println("===printBinary====> size:" + r.length);
		}

		if (r == null) {
			System.out.println("bytes is null !!!");
		} else {
			int idx = 0;
			for (byte b : r) {
				String str = Integer.toBinaryString(b & 0xff);
				while (str.length() < 8) {
					str = "0" + str;
				}

				System.out.print(str + "\t");

				++idx;
				if (idx % 8 == 0) {
					System.out.println();
				}
			}
		}
		System.out.println();
	}

	/**
	 * 以16进制方式打印
	 * 
	 * @param r
	 */
	public static void printHex(byte[] r) {
		if (r != null) {
			System.out.println("===printHex====> size:" + r.length);
		}
		
		if (r == null) {
			System.out.println("bytes is null !!!");
		} else {
			int idx = 0;
			for (byte b : r) {
				System.out.print(Integer.toHexString(b & 0xff) + "\t");
				++idx;
				if (idx % 16 == 0) {
					System.out.println();
				}
			}
		}
		System.out.println();
	}
	
	/**
	 * 打印 注册号<->注册类
	 */
	public static void printRegisterClass(){
		Map<Integer, Class<?>> ingeterClassMapping = CodedInfo.ingeterClassMapping;
		
		if(ingeterClassMapping==null){
			System.out.println("ingeterClassMapping is Null");
			return;
		}
		
		Set<Integer> keySet = ingeterClassMapping.keySet();
		Integer[] keyArray = keySet.toArray(new Integer[keySet.size()]);
		
		Arrays.sort(keyArray, new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2) {
				Integer f1 = (Integer) o1;
				Integer f2 = (Integer) o2;

				return f1-f2;
			}
		});
		
		for (int i = 0; i < keyArray.length; i++) {
			Class clz = ingeterClassMapping.get(keyArray[i]);
			System.out.println(keyArray[i] + "\t<->\t"+clz.getName());
		}
	}
	
	/**
	 * 打印 注册类 => 字段数
	 * 		  字段编号 >>字段名 
	 * @throws Exception 
	 */
	public static void printRegisterFields() throws Exception{
		Map<Integer, Class<?>> ingeterClassMapping = CodedInfo.ingeterClassMapping;
		
		if(ingeterClassMapping==null){
			System.out.println("ingeterClassMapping is Null");
			return;
		}
		
		Set<Integer> keySet = ingeterClassMapping.keySet();
		Integer[] keyArray = keySet.toArray(new Integer[keySet.size()]);
		
		Arrays.sort(keyArray, new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2) {
				Integer f1 = (Integer) o1;
				Integer f2 = (Integer) o2;

				return f1-f2;
			}
		});
		
		for (int i = 0; i < keyArray.length; i++) {
			Class clz = ingeterClassMapping.get(keyArray[i]);
			
			Field[] fields = CodedInfo.getClassFields(clz);
			System.out.println(clz.getName() + "\t=>\t"+ fields.length);
			for (int j = 0; j < fields.length; j++) {
				System.out.println(j + "\t>>\t"+ fields[j].getName());
			}
		}
	}
	
	/**
	 * 找到指定包下的所有类
	 *
	 *  @param pack
	 */
	public static void printMessageClass(String packName) throws Exception{
		String path =String.class.getResource("/").getPath()+packName.replace(".", "/");
		File packDir = new File(path);
		System.out.println(">>>>>>>>>> print package abs path:" +path );
		
		List<String> fileList = new ArrayList<String>();
		
		fillClassesName(fileList, packName+".", packDir);
		
		System.out.println("fileList size:"+fileList.size());
		for (String name : fileList) {
			System.out.println(name);
		}
	}
	
	private static void fillClassesName(List<String> fileList, String pack, File file){
		if(file.isDirectory()){
			for (File f : file.listFiles()) {
				if(f.isDirectory()){
					fillClassesName(fileList,pack+f.getName()+".", f);
				}else{
					fillClassesName(fileList,pack, f);
				}
			}
		}else{
			String name = file.getName();
			fileList.add(pack +name.substring(0, name.length()-6));
		}
	}
	
	public static void registerAllClz(String packName) throws Exception{
		String path =String.class.getResource("/").getPath()+packName.replace(".", "/");
		File packDir = new File(path);
		
		List<String> fileList = new ArrayList<String>();
		
		fillClassesName(fileList, packName+".", packDir);
		
		{
			fileList.add("com.xpec.c4.game.pet.PetSkill");
			fileList.add("com.xpec.c4.game.talent.TalentSlotIDInfo");
			fileList.add("com.xpec.c4.g3d.Vector3D");
			fileList.add("com.xpec.c4.game.unit.creature.constant.Gender");
			fileList.add("com.xpec.c4.game.unit.creature.constant.VocationType");
			fileList.add("com.xpec.c4.game.pet.PetAttribute");
			fileList.add("com.xpec.c4.expression.LimitHasGoods");
			fileList.add("m.Pr");
		}
		
		{
			fileList.remove("com.xpec.c4.message.mail.MailBox");
			fileList.remove("com.xpec.c4.message.mail.NewMail");
			fileList.remove("com.xpec.c4.message.mail.NewMailNotice");
			fileList.remove("com.xpec.c4.message.mail.ReadMail");
			fileList.remove("com.xpec.c4.message.character.SPlayerDetailInfo");
			fileList.remove("com.xpec.c4.message.goodssystem.equipment.EquipFOther");
			fileList.remove("com.xpec.c4.message.mail.ReceiveAttachment");
			fileList.remove("com.xpec.c4.message.character.CharGridUpd2");
			fileList.remove("com.xpec.c4.message.buff.BuffDurationUpdate");
			fileList.remove("com.xpec.c4.message.mail.OpenMailBox");
			fileList.remove("com.xpec.c4.message.character.SPetDetailInfo");
			fileList.remove("com.xpec.c4.message.kitbag.KitbagGoodsID");
			fileList.remove("com.xpec.c4.message.kitbag.KitbagGoodsInfo");
			fileList.remove("com.xpec.c4.message.kitbag.SKitbagInfo");
			fileList.remove("com.xpec.c4.message.MessageTypesUtility");
			fileList.remove("com.xpec.c4.message.onlinerewards.RandomRewardsInfo");
			fileList.remove("com.xpec.c4.message.login.CAccountCharacterListRequest");
			fileList.remove("com.xpec.c4.message.equipmentslot.EquipSlotTeam");
			fileList.remove("com.xpec.c4.message.shop.ExpenseItem");
			fileList.remove("com.xpec.c4.message.character.Cgu2");
			fileList.remove("com.xpec.c4.message.ui.SQuickBarResult");
			fileList.remove("com.xpec.c4.message.mail.BatchDeleteMail");
			fileList.remove("com.xpec.c4.message.character.CPeekPet");
			fileList.remove("com.xpec.c4.message.mail.BatchReceiveAttachment");
			fileList.remove("com.xpec.c4.message.character.Cgu1");
			fileList.remove("com.xpec.c4.message.mail.BriefMail");
			fileList.remove("com.xpec.c4.message.mail.DeleteMail");
			fileList.remove("com.xpec.c4.message.mail.FullMail");
			fileList.remove("com.xpec.c4.message.character.CharLod");
			fileList.remove("com.xpec.c4.message.effect.AvatarContent");
			fileList.remove("com.xpec.c4.message.reputation.CampSessionInfo");
			fileList.remove("com.xpec.c4.message.ContextStatus");
			fileList.remove("com.xpec.c4.message.character.SimplyCreatureInfo");
			fileList.remove("com.xpec.c4.message.kitbag.CMoveGoods");
			fileList.remove("com.xpec.c4.message.character.Relocation");
		}
		
		for (String name : fileList) {
			Class clz = Class.forName(name);
			if(clz.isEnum()){
				continue;
			}
			if(clz.getDeclaredFields().length>0){
				boolean had = false;
				for (Field field : clz.getDeclaredFields()) {
					if (!Modifier.isFinal(field.getModifiers()) && !Modifier.isStatic(field.getModifiers())
							&& !Modifier.isTransient(field.getModifiers())) {
						had=true;
						break;
					}
				}
				if(!had){
//					System.out.println("transient field: "+clz.getName());
					continue;
				}
			}
			
//			CodedInfo.registClass(clz);
			System.out.println("CodedInfo.registClass("+clz.getName()+".class);");
		}
		
//		CodedInfo.registerFields();
//		
//		printRegisterClass();
//		printRegisterFields();
	}
	
	/**
	 * 将数组转化成16进制的字符串
	 *
	 *  @param r
	 *  @return
	 */
	public static String transferToHexString(byte[] r) {
		if (r == null) {
			return null;
		} else {
			StringBuffer sb = new StringBuffer();
			for (byte b : r) {
				sb.append(Integer.toHexString(b & 0xff));
				sb.append(' ');
			}
			return sb.toString();
		}
	}
	
	/**
	 * 将 "1e 2a 3d 4f"这种格式转变为byte[]
	 *
	 *  @param str
	 *  @return
	 */
	public static byte[] transferToBytes(String str){
		if(str==null||str.length()==0){
			return null;
		}
		
		String[] strArr = str.split(" ");
		byte[] bs = new byte[strArr.length];
		for (int i = 0; i < strArr.length; i++) {
//			bs[i]=Byte.parseByte(strArr[i], 16);
			bs[i]=(byte)Integer.parseInt(strArr[i], 16);
		}
		
		return bs;
	}
	
	public static void main(String[] args) throws Exception {
//		Class clz = Class.forName("com.xpec.c4.message.biz.CFaceBuy");
//		printMessageClass("com.xpec.c4.message");
//		registerAllClz("com.xpec.c4.message");
		registerAllClz("m");
	}
}
